{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "35d27b44",
   "metadata": {},
   "source": [
    "# S21 simulation of a resonator\n",
    "\n",
    "Authors: Sara Buhktari, Christian Kraglund Andersen\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0b0da17a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import useful packages\n",
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, open_docs\n",
    "from qiskit_metal.toolbox_metal import math_and_overrides\n",
    "from qiskit_metal.qlibrary.core import QComponent\n",
    "from collections import OrderedDict\n",
    "\n",
    "# To create plots after geting solution data.\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "# Packages for the simple design\n",
    "from qiskit_metal.qlibrary.tlines.meandered import RouteMeander\n",
    "from qiskit_metal.qlibrary.tlines.pathfinder import RoutePathfinder\n",
    "from qiskit_metal.qlibrary.terminations.launchpad_wb_driven import LaunchpadWirebondDriven\n",
    "from qiskit_metal.qlibrary.terminations.open_to_ground import OpenToGround\n",
    "from qiskit_metal.qlibrary.terminations.short_to_ground import ShortToGround\n",
    "\n",
    "# Analysis\n",
    "# from qiskit_metal.renderers.renderer_gds.gds_renderer import QGDSRenderer\n",
    "# from qiskit_metal.analyses.quantization import EPRanalysis\n",
    "from qiskit_metal.analyses.quantization import EPRanalysis\n",
    "from qiskit_metal.analyses.simulation import ScatteringImpedanceSim\n",
    "from qiskit_metal.analyses.sweep_and_optimize.sweeping import Sweeping\n",
    "import pyEPR as epr"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c6e244f8",
   "metadata": {},
   "source": [
    "# Set up the design"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3983eac9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Set up chip dimensions \n",
    "design = designs.DesignPlanar()\n",
    "design._chips['main']['size']['size_x'] = '9mm'\n",
    "design._chips['main']['size']['size_y'] = '9mm'\n",
    "\n",
    "# Resonator and feedline gap width (W) and center conductor width (S) from reference 2\n",
    "design.variables['cpw_width'] = '15 um' #S from reference 2\n",
    "design.variables['cpw_gap'] = '9 um' #W from reference 2\n",
    "\n",
    "\n",
    "design.overwrite_enabled = True\n",
    "\n",
    "hfss = design.renderers.hfss\n",
    "\n",
    "# Open GUI\n",
    "gui = MetalGUI(design)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc2c100f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Define for renderer\n",
    "eig_qres = EPRanalysis(design, \"hfss\")\n",
    "hfss = design.renderers.hfss\n",
    "hfss = eig_qres.sim.renderer\n",
    "q3d = design.renderers.q3d"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "055c0bef",
   "metadata": {},
   "source": [
    "# Define the geometry\n",
    "\n",
    "Here we will have a single feedline couple to a single CPW resonator.\n",
    "\n",
    "The lauchpad should be included in the driven model simulations.\n",
    "\n",
    "For that reason, we use the LaunchpadWirebondDriven component which has an extra pin for input/output"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ef570ed8",
   "metadata": {},
   "outputs": [],
   "source": [
    "###################\n",
    "# Single feedline #\n",
    "###################\n",
    "\n",
    "# Driven Lauchpad 1\n",
    "x = '-1.5mm'\n",
    "y = '2.0mm'\n",
    "launch_options = dict(chip='main', pos_x=x, pos_y=y, orientation='360', lead_length='30um')\n",
    "LP1 = LaunchpadWirebondDriven(design, 'LP1', options = launch_options)\n",
    "\n",
    "# Driven Launchpad 2\n",
    "x = '1.5mm'\n",
    "y = '2.0mm'\n",
    "launch_options = dict(chip='main', pos_x=x, pos_y=y, orientation='180', lead_length='30um')\n",
    "LP2 = LaunchpadWirebondDriven(design, 'LP2', options = launch_options)\n",
    "\n",
    "# Using path finder to connect the two launchpads\n",
    "TL_LP1_LP2 = RoutePathfinder(design, 'TL_LP1_LP2', options = dict(chip='main', trace_width ='15um',\n",
    "        trace_gap ='9um',\n",
    "                                            fillet='99um',\n",
    "                                                                  \n",
    "        hfss_wire_bonds = True,\n",
    "                                            lead=dict(end_straight='1.972mm'),\n",
    "                                            pin_inputs=Dict(\n",
    "                                                start_pin=Dict(\n",
    "                                                    component='LP1',\n",
    "                                                    pin='tie'),\n",
    "                                                end_pin=Dict(\n",
    "                                                    component='LP2',\n",
    "                                                    pin='tie')\n",
    "                                            )))\n",
    "\n",
    "\n",
    "# Rebuild the GUI\n",
    "gui.rebuild()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92b1570a",
   "metadata": {},
   "outputs": [],
   "source": [
    "######################\n",
    "# lambda/2 resonator #\n",
    "######################\n",
    "\n",
    "# First we define the two end-points\n",
    "otg1 = OpenToGround(design, 'otg1s', options=dict(chip='main', pos_x='-0.3mm',  pos_y='1.968mm', orientation='180'))\n",
    "otg2 = OpenToGround(design, 'otg1e', options=dict(chip='main', pos_x='0.0mm',  pos_y='0.0mm', orientation='270'))\n",
    "\n",
    "# Use RouteMeander to fix the total length of the resonator\n",
    "rt_meander = RouteMeander(design, 'meander',  Dict(\n",
    "        trace_width ='12um',\n",
    "        trace_gap ='5um',\n",
    "        total_length='8.0mm',\n",
    "        hfss_wire_bonds = True,\n",
    "        fillet='99 um',\n",
    "        lead = dict(start_straight='250um'),\n",
    "        pin_inputs=Dict(\n",
    "            start_pin=Dict(component='otg1s', pin='open'),\n",
    "            end_pin=Dict(component='otg1e', pin='open')), ))\n",
    "\n",
    "# rebuild the GUI\n",
    "gui.rebuild()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9956dd38",
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.autoscale()\n",
    "gui.screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8bd2910a",
   "metadata": {},
   "source": [
    "# Scattering Analysis"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be209d2e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.simulation import ScatteringImpedanceSim\n",
    "em1 = ScatteringImpedanceSim(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "504994dd",
   "metadata": {},
   "outputs": [],
   "source": [
    "design_name= \"Sweep_DrivenModal\"\n",
    "qcomp_render = [] # Means to render everything in qgeometry table.\n",
    "open_terminations = []\n",
    "\n",
    "# Here, pin LP1_in and LP2_in are converted into lumped ports,\n",
    "#           each with an impedance of 50 Ohms. <br>\n",
    "port_list = [('LP1', 'in', 50),\n",
    "             ('LP2', 'in', 50)]\n",
    "box_plus_buffer = True"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "be7762a9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# we use HFSS as rendere\n",
    "hfss = em1.renderer\n",
    "hfss.start()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6bd25114",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Here we activate the design for a drivenmodal solution\n",
    "hfss.activate_ansys_design(\"HangingResonator\", 'drivenmodal')\n",
    "setup_args = Dict(max_delta_s=0.001)\n",
    "setup_args.name = 'Setup'\n",
    "hfss.edit_drivenmodal_setup(setup_args)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5c8fc60c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# set buffer\n",
    "hfss.options['x_buffer_width_mm'] = 0.1\n",
    "hfss.options['y_buffer_width_mm'] = 0.1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "522ca07a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# clean the design if needed\n",
    "hfss.clean_active_design()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d685f9fc",
   "metadata": {},
   "outputs": [],
   "source": [
    "# render the design\n",
    "hfss.render_design(selection=[], \n",
    "                   open_pins=open_terminations, \n",
    "                   port_list=port_list, \n",
    "                   box_plus_buffer = box_plus_buffer)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8a316652",
   "metadata": {},
   "outputs": [],
   "source": [
    "# for acurate simulations, make sure the mesh is fine enough for the meander\n",
    "hfss.modeler.mesh_length(\n",
    "                'cpw_mesh',\n",
    "                ['trace_meander'],\n",
    "                MaxLength='0.01mm')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ad348ed",
   "metadata": {},
   "source": [
    "# Broad sweet to find the resonance"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e65e1ab2",
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.add_sweep(setup_name=\"Setup\", \n",
    "               name=\"Sweep\", \n",
    "               start_ghz=4.0,\n",
    "               stop_ghz=8.0,\n",
    "               count=2001,\n",
    "               type=\"Interpolating\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bdeac158",
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.analyze_sweep('Sweep', 'Setup')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "522904f7",
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.plot_params(['S11', 'S21'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c1f26b38",
   "metadata": {},
   "outputs": [],
   "source": [
    "# extract the S21 parameters\n",
    "freqs, Pcurves, Pparams = hfss.get_params(['S21'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c71579a",
   "metadata": {},
   "outputs": [],
   "source": [
    "# find armin \n",
    "f_res = freqs[np.argmin(np.abs(Pparams.S21.values))]\n",
    "f_res"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "43df3d00",
   "metadata": {},
   "source": [
    "# Narrow sweep around the resonance found above"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "50ddb791",
   "metadata": {},
   "outputs": [],
   "source": [
    "#fine sweep\n",
    "hfss.add_sweep(setup_name=\"Setup\", \n",
    "               name=\"Sweep_narrow\", \n",
    "               start_ghz=np.round(f_res/1e9,3)-0.01,\n",
    "               stop_ghz=np.round(f_res/1e9,3)+0.01,\n",
    "               count=1001,\n",
    "               type=\"Fast\") #slow but precise"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffea4175",
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.analyze_sweep('Sweep_narrow', 'Setup')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f06626b4",
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.plot_params(['S11', 'S21'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "743b8dcf",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "c72f2f6d",
   "metadata": {},
   "source": [
    "# Close connections"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "80694931",
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "13927800",
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.disconnect_ansys()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dc2621b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "gui.main_window.close()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6d7375c2",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "81863bcc",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python [conda env:metal]",
   "language": "python",
   "name": "conda-env-metal-py"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.8"
  },
  "latex_envs": {
   "LaTeX_envs_menu_present": true,
   "autoclose": false,
   "autocomplete": true,
   "bibliofile": "biblio.bib",
   "cite_by": "apalike",
   "current_citInitial": 1,
   "eqLabelWithNumbers": true,
   "eqNumInitial": 1,
   "hotkeys": {
    "equation": "Ctrl-E",
    "itemize": "Ctrl-I"
   },
   "labels_anchors": false,
   "latex_user_defs": false,
   "report_style_numbering": false,
   "user_envs_cfg": false
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
